package util

import (
	"bufio"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

type fileEntry struct {
	name string
	path string
}

func (f *fileEntry) Name() string {
	return f.name
}

func (f *fileEntry) Path() string {
	return f.path
}

func (f *fileEntry) Url() string {
	return fmt.Sprintf("%s%c%s", f.path, filepath.Separator, f.name)
}

type FileEntry interface {
	Name() string
	Path() string
	Url() string
}

func GetNameAndPathInDir(folder string) []FileEntry {
	if strings.HasSuffix(folder, fmt.Sprintf("%c", filepath.Separator)) {
		folder = folder[:len(folder)-1]
	}
	fileEntrys := make([]FileEntry, 0)
	fileEntrys = getNameAndPathInDir(folder, fileEntrys)
	return fileEntrys
}
func getNameAndPathInDir(folder string, outFiles []FileEntry) []FileEntry {
	fileList, err := os.ReadDir(folder)
	if err != nil {
		return outFiles
	}

	for _, file := range fileList {
		if file.IsDir() {
			inFolder := fmt.Sprintf("%s%c%s", folder, filepath.Separator, file.Name())
			outFiles = getNameAndPathInDir(inFolder, outFiles)
		} else {
			fileEntry := fileEntry{name: file.Name(), path: folder}
			outFiles = append(outFiles, &fileEntry)
		}
	}
	return outFiles
}

func FileMd5(file FileEntry) string {
	file0, err := os.Open(file.Url())
	if err != nil {
		fmt.Println(err)
		return ""
	}
	defer file0.Close()
	hasher := md5.New()
	if _, err := io.Copy(hasher, file0); err != nil {
		return ""
	}
	return hex.EncodeToString(hasher.Sum(nil))
}

func ReadFileAsText(file FileEntry) string {
	file0, err := os.Open(file.Url())
	if err != nil {
		fmt.Println(err)
		return ""
	}
	defer file0.Close()

	var builder strings.Builder
	scanner := bufio.NewScanner(file0)
	for scanner.Scan() {
		line := scanner.Text()
		builder.WriteString(line)
	}
	return builder.String()
}

func ReadFileAsLines(file FileEntry) []string {
	file0, err := os.Open(file.Url())
	if err != nil {
		fmt.Println(err)
		return make([]string, 0)
	}
	defer file0.Close()

	lines := make([]string, 0)
	scanner := bufio.NewScanner(file0)
	for scanner.Scan() {
		line := scanner.Text()
		lines = append(lines, line)
	}
	return lines
}

func WriteFileWithLines(file FileEntry, lines []string) {
	file0, err := os.OpenFile(file.Url(), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file0.Close()

	for _, line := range lines {
		file0.WriteString(line)
		file0.WriteString("\n")
	}
}
